package com.ztesoft.zsmart.zcm.dialing.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Properties;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import com.ztesoft.zsmart.core.log.ZSmartLogger;
import org.apache.commons.io.IOUtils;

public final class SSHUtil {

    private static final ZSmartLogger logger = ZSmartLogger.getLogger(SSHUtil.class);

    private static final String ENCODING = "UTF-8";

    private SSHUtil() {

    }

    public static Session getJSchSession(String userName, String password, String host, Integer port, Integer timeOut) throws JSchException {
        JSch jsch = new JSch();
        Session session = null;
        session = jsch.getSession(userName, host, port);
        session.setPassword(password);
        Properties config = new Properties();
        config.put("StrictHostKeyChecking", "no");
        session.setConfig(config);
        session.setTimeout(timeOut);
        session.connect();
        return session;
    }

    public static String shellCommandByJSch(Session session, String command) {
        StringBuilder result = new StringBuilder();
        Channel channel = null;
        OutputStream outputstream_for_the_channel = null;
        InputStream inputstream_from_the_channel = null;
        PrintStream commander = null;
        BufferedReader br = null;
        try {
            channel = session.openChannel("shell");
            outputstream_for_the_channel = channel.getOutputStream();
            commander = new PrintStream(outputstream_for_the_channel, true, ENCODING);
            channel.connect();
            commander.println(command);
            commander.println("exit");
            commander.close();
            inputstream_from_the_channel = channel.getInputStream();
            br = new BufferedReader(new InputStreamReader(inputstream_from_the_channel, ENCODING));
            String line;
            while ((line = br.readLine()) != null) {
                result.append(line);
                logger.info(line);
            }
        }
        catch (Exception e) {
            logger.error(e.getMessage());
        }
        finally {
            opsClose(outputstream_for_the_channel);
            ipsClose(inputstream_from_the_channel);
            if (br != null) {
                try {
                    br.close();
                }
                catch (IOException e) {
                    logger.error(e);
                }
            }
        }
        return result.toString();
    }

    public static String execCommandByJSch(Session session, String command) {
        String result = null;
        ChannelExec channelExec = null;
        InputStream in = null;
        try {
            channelExec = (ChannelExec) session.openChannel("exec");
            in = channelExec.getInputStream();
            channelExec.setCommand(command);
            channelExec.setErrStream(System.err);
            channelExec.connect();
            result = IOUtils.toString(in, ENCODING);
        }
        catch (Exception e) {
            logger.error(e.getMessage());
        }
        finally {
            if (in != null) {
                try {
                    in.close();
                }
                catch (IOException e) {
                    logger.error(e.getMessage());
                }
            }
            channelDisconnect(channelExec);
        }
        return result;
    }

    public static boolean uploadFileIsNotDirectory(Session session, String localFilePath, String targetFilePath)
        throws JSchException, SftpException, IOException {
        ChannelSftp sftp = null;
        InputStream in = null;
        try {
            sftp = (ChannelSftp) session.openChannel("sftp");
            sftp.connect();
            sftp.cd(targetFilePath);
            File file = new File(localFilePath);
            in = new FileInputStream(file);
            sftp.put(in, file.getName());
            return true;
        }
        catch (Exception e) {
            logger.error(e.getMessage());
            return false;
        }
        finally {
            if (null != in) {
                ipsClose(in);
            }
            if (null != sftp) {
                channelDisconnect(sftp);
            }
        }
    }

    private static void ipsClose(InputStream inputstream_from_the_channel) {
        if (inputstream_from_the_channel != null) {
            try {
                inputstream_from_the_channel.close();
            }
            catch (IOException e) {
                logger.error(e);
            }
        }
    }

    private static void opsClose(OutputStream outputstream_for_the_channel) {
        if (outputstream_for_the_channel != null) {
            try {
                outputstream_for_the_channel.close();
            }
            catch (IOException e) {
                logger.error(e);
            }
        }
    }

    private static void channelDisconnect(Channel channel) {
        if (channel != null) {
            channel.disconnect();
        }
    }

}
